package reci.journal.windows;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Arrays;

import javax.imageio.ImageIO;
import javax.swing.*;

import reci.journal.Const;
import reci.journal.GlobalSettings;
import reci.journal.Journal;
import reci.journal.Main;
import reci.journal.utils.Util;

/*
 * Copyright (C) 2014 ReciGames
 * See notice in reci.journal.Main.java.
 */

/**UI to create and access journals*/
public class LoginWindow extends JFrame implements MouseListener, KeyListener
{
	private static final long serialVersionUID = 1L;

	private Main main;
	
	private JTextField journal;
	private String currentJournalText="";
	
	private JPasswordField pass;
	private JLabel passL2;
	private JLabel pass2L;
	private JPasswordField pass2;
	
	private JLabel submit;
	private JLabel cancel;
	
	/**
	 * @param m
	 */
	public LoginWindow(Main m)
	{
		this(m,GlobalSettings.getDefaultRjPath());
	}
	
	/**
	 * @param m
	 * @param journalPath
	 */
	public LoginWindow(Main m, String journalPath)
	{
		main=m;
		initUi();
		selectJournal(journalPath);
	}
	
	/**
	 * Initializes UI.
	 */
	private void initUi()
	{
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		setSize(400,400);
		setLocationRelativeTo(null);
		setTitle("Welcome");
		setResizable(false);
		setVisible(true);
		
		addKeyListener(this);
		
		addWindowListener(new WindowAdapter()
		{
			public void windowClosing(WindowEvent e)
			{
				((LoginWindow)e.getSource()).exit();
			}
		});
		
		Container cp=getContentPane();
		cp.setLayout(null); 
		//cp.setBackground(new Color(0xcc,0xcc,0xcc));
		
		
		
		//font for jwhatever text
		Font font=new Font("Arial",Font.PLAIN,10);
		Font bold=new Font("Arial",Font.BOLD,12);
		JLabel jl;
		
		int px=100;
		int py=150;
		
		//fields
		JLabel journalL=new JLabel("Journal");
		journalL.setBounds(0+px,0+py,200,30);
		journalL.setFont(bold);
		cp.add(journalL);
		
		JLabel j=new JLabel("(path for new or existing journal)",SwingConstants.RIGHT);
		j.setBounds(0+px,0+py,200,30);
		j.setFont(font);
		cp.add(j);
		
		journal=new JTextField();
		journal.setBounds(0+px,25+py,200,30);
		journal.addKeyListener(this);
		journal.addMouseListener(this);
		cp.add(journal);
		
		JLabel passL=new JLabel("Password");
		passL.setBounds(0+px,50+py,200,30);
		passL.setFont(bold);
		cp.add(passL);
		
		passL2=new JLabel("(keep empty for no password)",SwingConstants.RIGHT);
		passL2.setBounds(0+px,50+py,200,30);
		passL2.setFont(font);
		passL2.setVisible(false);
		cp.add(passL2);
		
		pass=new JPasswordField();
		pass.setBounds(0+px,75+py,200,30);
		pass.addKeyListener(this);
		cp.add(pass);
		
		pass2L=new JLabel("Confirm password");
		pass2L.setBounds(0+px,100+py,200,30);
		pass2L.setVisible(false);
		pass2L.setFont(bold);
		cp.add(pass2L);
		
		pass2=new JPasswordField();
		pass2.setBounds(0+px,125+py,200,30);
		pass2.setVisible(false);
		pass2.addKeyListener(this);
		cp.add(pass2);
		
		
		
		//button styling
		Color btnColor=new Color(0,0,0x99);
		Color btnTextColor=new Color(0xff,0xff,0xff);
		
		//submit (log in / create)
		submit=new JLabel("Login",SwingConstants.CENTER);
		submit.setBounds(0+px,120+py,95,35);
		submit.setFont(bold);
		submit.setOpaque(true);
		submit.setBackground(btnColor);
		submit.setForeground(btnTextColor);
		submit.addMouseListener(this);
		cp.add(submit);
		
		//exit
		cancel=new JLabel("Exit",SwingConstants.CENTER);
		cancel.setBounds(105+px,submit.getY(),95,35);
		cancel.setFont(bold);
		cancel.setOpaque(true);
		cancel.setBackground(btnColor);
		cancel.setForeground(btnTextColor);
		cancel.addMouseListener(this);
		cp.add(cancel);
		
		
		
		//logo
		try
		{
			InputStream is=getClass().getResourceAsStream("/logo100.png");
			BufferedImage logo=ImageIO.read(is);
			jl=new JLabel(new ImageIcon(logo));
			jl.setBounds(150,10,100,100);
			cp.add(jl);
		}
		catch(Exception e)
		{}
		
		jl=new JLabel(Const.APP_NAME+" v."+Const.VERSION,SwingConstants.CENTER);
		jl.setBounds(100,115,200,30);
		jl.setFont(font);
		cp.add(jl);
		
		
		
		//refresh GUI
		repaint();
	}
	
	/**
	 * Destroys window.
	 */
	private void destroy()
	{
		this.setVisible(false);
		this.dispose();
	}
	
//key listener
	public void keyPressed(KeyEvent k)
	{}

	public void keyReleased(KeyEvent k)
	{
		if(k.getKeyChar()==KeyEvent.VK_ENTER)
		{
			jlabelClicked(submit.getText());
		}
		else
		{
			String t=journal.getText();
			if(!t.equals(currentJournalText))
			{
				currentJournalText=t;
				autoShowHideCreateJournal();
			}
		}
	}

	public void keyTyped(KeyEvent e)
	{}
	
//mouse listener
	public void mouseClicked(MouseEvent e)
	{
		if(e.getSource() instanceof JLabel)
		{
			String t=((JLabel)e.getSource()).getText();
			jlabelClicked(t);
		}
		else if(e.getSource() instanceof JTextField)
		{
			//focused on journal textfield
			try
			{
				JFileChooser chooser=new JFileChooser(new File(journal.getText()).getParent());
				chooser.showDialog(null,"Select");
				String path=chooser.getSelectedFile().getAbsolutePath();
				selectJournal(path);
			}
			catch(Exception ex)
			{}
		}
	}

	public void mouseEntered(MouseEvent me)
	{}
	
	public void mouseExited(MouseEvent me)
	{}
	
	public void mousePressed(MouseEvent me)
	{}
	
	public void mouseReleased(MouseEvent me)
	{}
	
	/**
	 * Selects a journal.
	 * 
	 * @param path
	 */
	private void selectJournal(String path)
	{
		if(!path.endsWith(".rj"))
		{
			path+=".rj";
		}
		
		journal.setText(path);
		
		boolean isPasswordProtected=Journal.isPasswordProtected(path);
		
		if(isPasswordProtected)
		{
			pass.grabFocus();
		}
		
		currentJournalText=path;
		autoShowHideCreateJournal();
	}
	
	/**
	 * Clicked a JLabel.
	 * 
	 * @param text
	 */
	private void jlabelClicked(String text)
	{
		if(text.equals("Login"))
		{
			login();
		}
		else if(text.equals("Exit"))
		{
			exit();
		}
		else if(text.equals("Create"))
		{
			create();
		}
		else if(text.equals("Cancel"))
		{
			blurAddNew();
		}
	}
	
	/**
	 * Exits window.
	 */
	private void exit()
	{
		destroy();
		main.destroy();
	}
	
	/**
	 * Shows correct form in UI.
	 */
	private void autoShowHideCreateJournal()
	{
		if(new File(currentJournalText).exists())
		{
			boolean isPasswordProtected=Journal.isPasswordProtected(currentJournalText);
			pass.setEnabled(isPasswordProtected);
			
			blurAddNew();
		}
		else
		{
			focusAddNew();
		}
	}
	
	/**
	 * Shows "create new journal" form.
	 */
	private void focusAddNew()
	{
		pass.setEnabled(true);
		
		passL2.setVisible(true);
		pass2L.setVisible(true);
		pass2.setVisible(true);
		
		submit.setText("Create");
		moveJLabelY(submit,315);
		cancel.setText("Cancel");
		moveJLabelY(cancel,315);
	}
	
	/**
	 * Exits "create new journal" form.
	 */
	private void blurAddNew()
	{
		pass2.setText("");
		passL2.setVisible(false);
		pass2L.setVisible(false);
		pass2.setVisible(false);
		
		submit.setText("Login");
		moveJLabelY(submit,270);
		cancel.setText("Exit");
		moveJLabelY(cancel,270);
		cancel.setVisible(true);
		
		repaint();
	}
	
	/**
	 * Moves JLabel.y
	 * 
	 * @param j
	 * @param deltaY
	 */
	private void moveJLabelY(JLabel j, int deltaY)
	{
		j.setLocation(j.getX(),deltaY);
	}
	
	/**
	 * Creates new journal.
	 */
	private void create()
	{
		//
		// check inputs
		//
		
		//filepath
		String filepath=journal.getText();
		if(filepath.equals(""))
		{
			journal.grabFocus();
			return;
		}
		
		//already exists
		if(new File(filepath).exists())
		{
			Util.alert("A file with that name already exists.");
			journal.grabFocus();
			return;
		}
		
		//pass, confirm
		char[] p1=pass.getPassword();
		char[] p2=pass2.getPassword();
		
		boolean arePasswordsEqual=Arrays.equals(p1,p2);

		Arrays.fill(p1,(char)0);
		Arrays.fill(p2,(char)0);
		
		if(!arePasswordsEqual)
		{
			Util.alert("Passwords do not match.");
			pass.grabFocus();
			return;
		}
		
		//
		// input was valid
		//
		
		login();
	}
	
	/**
	 * Logs in to existing journal.
	 */
	private void login()
	{
		String journalPath=journal.getText();
		char[] p1=pass.getPassword();//used as Journal.password, so don't clear
		
		try
		{
			Journal.login(journalPath,p1);
			new MainWindow(main);
			destroy();
		}
		//wrong password or error opening
		catch(Exception e)
		{
			Util.alert("Access denied.",e);
			pass.selectAll();
			pass.requestFocus();
		}
	}
}
